#include "s3c2440.h"
#include "uart.h"
#include "pll.h"

#define FREQ_IN 12000000
#define TRUE    1
#define FAIL    0
//bEnable = '1' Turn on Mpll
//bEnable = '0' Turn off Mpll
void TurnOnMpll(unsigned char bEnable)
{

    if(bEnable)
        {
        CLKSLOW &= ~MPLL_OFF;
        }
    else
        {
        SlowEnable(TRUE);
        CLKSLOW |= MPLL_OFF;
        }
}

void SlowEnable(unsigned char bEnable)
{
    if(bEnable)
        {
        CLKSLOW |= SLOW;
        }
    else
        {
        CLKSLOW &= ~SLOW;
        }
}
void ChangeMpll(unsigned int mdiv,unsigned int pdiv,unsigned int sdiv)
{
    unsigned i;
    LOCKTIME &= ~0XFFFF;        //MASK M_TIME
    LOCKTIME |= 0X0FFF;         //SET M_TIME

    UPLLCON = (56 << 12) |(2 << 4) | 2;
    i = 0;
    while(i == 7)
        {
        i++;
        }

    MPLLCON = (mdiv << 12)|(pdiv << 4) | sdiv;



}
unsigned int GetMpllClk(void)
{
    unsigned int temp;
    unsigned int m;
    unsigned int p;
    unsigned int s;

    m = (MPLLCON >> 12) & 0XFF;
    p = (MPLLCON >> 4) & 0X3F;
    s = (MPLLCON & 0X3);
    temp = 2 * (m + 8) * FREQ_IN/(p+2);
    return (temp >> s);
}
unsigned int GetFclk(void)
{
    unsigned int temp;

    if(0 == (CLKSLOW & SLOW))
        {
        return GetMpllClk();
        }
    else
        {
        temp = CLKSLOW & 0X7;   //get slow value;
        if(temp == 0)
            {
            return FREQ_IN;
            }
        else
            return (FREQ_IN >> temp);
        }
}

unsigned int GetHclk(void)
{
    unsigned int temp;
    temp = (CLKDIVN >> 1) & 0X3;
    switch(temp)
        {
        case 0:
                return GetFclk();break;
        case 1:
                return GetFclk()/2;break;
        case 2:
                {
                if(0 == (CAMDIVN & HCLK4_HALF))
                    {
                    return GetFclk()/4;
                    }
                else
                    {
                    return GetFclk()/8;
                    }
                break;
                }
        case 3:
                {
                if(0 == (CAMDIVN & HCLK3_HALF))
                    {
                    return GetFclk()/3;
                    }
                else
                    {
                    return GetFclk()/6;
                    }
                break;
                }
        }
    return 0;
}

unsigned int GetPclk(void)
{
    if(CLKDIVN & PDIVN)
        {
        return GetHclk()/2;
        }
    else
        {
        return GetHclk();
        }
}
